// Session
package core

import (
	"bufio"
	"net"
	"sync"
	"time"
)

var (
	READ_BUFFER_SIZE        = 1024 * 4
	READ_TIME_IDLE          = int64(30) //读空闲时间秒级别
	WRITE_TIME_IDLE         = int64(30) //写空闲时间秒级别
	WRITE_MESSAGE_CHAN_SIZE = 1024
)

type Session struct {
	Conn             net.Conn
	SessionId        int64
	closeSign        chan bool
	LastReadTime     int64
	LastWriteTime    int64
	ReadTimeOutChan  chan bool
	WriteTimeOutChan chan bool
	WriteChannel     chan *Message
	FilterChan       *FilterChan
	InBuff           *ByteBuf
	OutBuff          *ByteBuf
	//自己定义一些状态
	State interface{}
}

// Buffered connection.
type bufferConn struct {
	net.Conn
	reader *bufio.Reader
}

func NewBufferSession(conn net.Conn, serverEngin *ServerEngin) *Session {
	now := time.Now().Unix()
	bC := newBufferConn(conn, READ_BUFFER_SIZE)
	session := &Session{
		Conn:             bC,
		SessionId:        NewSessionId(),
		closeSign:        make(chan bool, 1),
		LastReadTime:     now,
		LastWriteTime:    now,
		ReadTimeOutChan:  make(chan bool, 1),
		WriteTimeOutChan: make(chan bool, 1),
		WriteChannel:     make(chan *Message, WRITE_MESSAGE_CHAN_SIZE),
		InBuff:           NewByteBuf(serverEngin.BytePoll),
		OutBuff:          NewByteBuf(serverEngin.BytePoll),
		FilterChan:       serverEngin.FilterChan,
	}
	return session
}

func (session *Session) newListener(serverEngin *ServerEngin) {
	defer CoreRecover()
	defer session.Close(serverEngin)

	f := session.FilterChan.Head
	if f == nil {
		panic("FilterChan is not initlizer")
		return
	}
	for {
		select {
		case <-session.closeSign:
			return
		case <-session.ReadTimeOutChan:
			f.ReadTimeIdle(session)
		case <-session.WriteTimeOutChan:
			f.WriteTimeIdle(session)
		case msg := <-session.WriteChannel:
			session.FilterChan.Tail.MessageWrite(session, msg, serverEngin)
		default:
			f.MessageRecieved(session, session.InBuff, serverEngin)
		}
	}
}

func (session *Session) Close(serverEngin *ServerEngin) {
	serverEngin.SessionManager.Remove(session.SessionId)
	session.InBuff.Free()
	session.OutBuff.Free()
	session.Conn.Close()
	f := session.FilterChan.Head
	if f == nil {
		return
	}
	f.SessionClosed(session, serverEngin)
}

func (conn *bufferConn) Read(d []byte) (int, error) {
	return conn.reader.Read(d)
}

func newBufferConn(conn net.Conn, readBufferSize int) *bufferConn {
	return &bufferConn{
		conn,
		bufio.NewReaderSize(conn, readBufferSize),
	}
}

//func (session *Session) listener(serverEngin *ServerEngin) {
//	defer CoreRecover()
//	defer session.Conn.Close()
//	defer serverEngin.SessionManager.Remove(session.SessionId)
//	defer func() {
//		serverEngin.Handler.SessionClosed(session, serverEngin)
//	}()
//	request := make([]byte, 128)
//	left := make([]byte, 0)
//	for {
//		select {
//		case <-session.closeSign:
//			return
//		case <-session.ReadTimeOutChan:
//			serverEngin.Handler.ReadTimeIdle(session)
//		case <-session.WriteTimeOutChan:
//			serverEngin.Handler.WriteTimeIdle(session)
//		case msg := <-session.WriteChannel:
//			//fmt.Println("发送数据")
//			session.write(msg, serverEngin)
//		default:
//			lenth, err := session.Read(request)
//			if err != nil {
//				CoreLogger.Errorf("coreReadErroe (%s)read (%d)byte valuse: (%s)error", string(session.Ip), lenth, request[:lenth])
//				//				fmt.Println("读取数据异常", err)
//				return
//			}
//			//if lenth == 0 {
//			//	fmt.Println("客户端关闭了连接")
//			//	return
//			//}

//			left = append(left, request[:lenth]...)
//			for {
//				var message *Message
//				left, message, err = serverEngin.CodeFactory.Decode(left, serverEngin, session)
//				if err != nil {
//					CoreLogger.Errorf("decode Error (%s)", err)
//					return
//				}
//				if message == nil {
//					//					CoreLogger.Errorf("message is nil,message t", string(session.Ip), lenth, request[:lenth])
//					fmt.Println("读取数据异常", err)
//					break
//				}
//				serverEngin.Handler.MessageRecieved(session, message, serverEngin)
//			}
//		}
//	}
//}

////将消息写入
//func (session *Session) write(msg *Message, serverEngin *ServerEngin) {
//	b, err := serverEngin.CodeFactory.Encode(msg)
//	if err != nil {
//		CoreLogger.Errorf("encode Error (%s)", err)
//		session.close()
//		return
//	}
//	session.Write(b)
//}

//关闭session
func (session *Session) CloseSign() {
	session.closeSign <- true
}

//写消息
func (session *Session) writeMsg(msg *Message) {
	session.WriteChannel <- msg
}

var sessionId int64

//sessionid的生成锁
var sessionlock sync.Mutex

func NewSessionId() int64 {
	defer sessionlock.Unlock()
	sessionlock.Lock()
	sessionId++
	return sessionId
}
